<!DOCTYPE html>
<html lang="zh-CN" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>javascript高级程序设计（第4版）笔记-2 | Nuobel</title>
    <meta name="description" content="Nuobel 诺贝尔的源泉">
    <link rel="preload stylesheet" href="/assets/style.6550a0c8.css" as="style">
    <link rel="modulepreload" href="/assets/app.6facf8ba.js">
    <link rel="modulepreload" href="/assets/blog_readingNotes_jsgc4-2.md.754107dd.lean.js">
    
    <meta name="theme-color" content="#3c8772">
  <script>var _hmt=_hmt||[];(function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?b812ad2761f4f77a87ce9b80c0cae4a0";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)})();</script>
  <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-93a960b4><!--[--><!--]--><!--[--><span tabindex="-1" data-v-151f2593></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-151f2593> Skip to content </a><!--]--><!----><header class="VPNav" data-v-93a960b4 data-v-0fa0e57d><div class="VPNavBar has-sidebar" data-v-0fa0e57d data-v-be450ad9><div class="container" data-v-be450ad9><div class="title" data-v-be450ad9><div class="VPNavBarTitle has-sidebar" data-v-be450ad9 data-v-6d2fb2d9><a class="title" href="/" data-v-6d2fb2d9><!--[--><!--]--><!----><!--[-->Nuobel<!--]--><!--[--><!--]--></a></div></div><div class="content" data-v-be450ad9><div class="curtain" data-v-be450ad9></div><div class="content-body" data-v-be450ad9><!--[--><!--]--><!----><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-be450ad9 data-v-bdedfc22><span id="main-nav-aria-label" class="visually-hidden" data-v-bdedfc22>Main Navigation</span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/blog/frontend/library.html" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->博客<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/blog/summary/20210806.html" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->日记周记<!--]--><!----></a><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup active" data-v-bdedfc22 data-v-96001b6b><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-96001b6b><span class="text" data-v-96001b6b><!----> 读书笔记 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-96001b6b><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-96001b6b><div class="VPMenu" data-v-96001b6b data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-b66affaf><p class="title" data-v-b66affaf>前端技术</p><!--[--><!--[--><div class="VPMenuLink" data-v-b66affaf data-v-a5bbb52c><a class="VPLink link" href="/blog/svg/rumen.html" data-v-a5bbb52c data-v-30c06bd3><!--[-->SVG基础入门<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-b66affaf data-v-a5bbb52c><a class="VPLink link" href="/blog/readingNotes/browserPrinciple.html" data-v-a5bbb52c data-v-30c06bd3><!--[-->浏览器工作原理与实践<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-b66affaf data-v-a5bbb52c><a class="VPLink link" href="/blog/readingNotes/reactAndNodeJS.html" data-v-a5bbb52c data-v-30c06bd3><!--[-->react+Node.js开发实战<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-b66affaf data-v-a5bbb52c><a class="VPLink link" href="/blog/readingNotes/jsgc4.html" data-v-a5bbb52c data-v-30c06bd3><!--[-->javascript高级程序设计第4版<!--]--><!----></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/blog/interviews/" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->面试<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/photograph/home.html" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->摄影<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/english/plan.html" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->英语<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/wemedia/what.html" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->自媒体<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/life/index.html" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->生活<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/about/me.html" data-v-bdedfc22 data-v-95f5d58b data-v-30c06bd3><!--[-->关于 <!--]--><!----></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-be450ad9 data-v-da3f667a><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-da3f667a data-v-0d529b6d data-v-f3c41672><span class="check" data-v-f3c41672><span class="icon" data-v-f3c41672><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-0d529b6d><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-0d529b6d><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><!----><div class="VPFlyout VPNavBarExtra extra" data-v-be450ad9 data-v-66bb1f24 data-v-96001b6b><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-96001b6b><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-96001b6b><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-96001b6b><div class="VPMenu" data-v-96001b6b data-v-e7ea1737><!----><!--[--><!--[--><!----><div class="group" data-v-66bb1f24><div class="item appearance" data-v-66bb1f24><p class="label" data-v-66bb1f24>Appearance</p><div class="appearance-action" data-v-66bb1f24><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-66bb1f24 data-v-0d529b6d data-v-f3c41672><span class="check" data-v-f3c41672><span class="icon" data-v-f3c41672><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-0d529b6d><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-0d529b6d><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><!----><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-be450ad9 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div></div><!----></header><div class="VPLocalNav" data-v-93a960b4 data-v-2817d72e><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-2817d72e><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-2817d72e><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-2817d72e>菜单</span></button><a class="top-link" href="#" data-v-2817d72e>回到顶部</a></div><aside class="VPSidebar" data-v-93a960b4 data-v-c79ccefa><div class="curtain" data-v-c79ccefa></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-c79ccefa><span class="visually-hidden" id="sidebar-aria-label" data-v-c79ccefa> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="group" data-v-c79ccefa><section class="VPSidebarItem level-0 has-active" data-v-c79ccefa data-v-b05232f3><div class="item" role="button" data-v-b05232f3><div class="indicator" data-v-b05232f3></div><a class="VPLink link" data-v-b05232f3 data-v-30c06bd3><!--[--><h2 class="text" data-v-b05232f3>javascript高级程序设计第4版</h2><!--]--><!----></a><!----></div><div class="items" data-v-b05232f3><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b05232f3 data-v-b05232f3><div class="item" data-v-b05232f3><div class="indicator" data-v-b05232f3></div><a class="VPLink link link" href="/blog/readingNotes/jsgc4.html" data-v-b05232f3 data-v-30c06bd3><!--[--><p class="text" data-v-b05232f3>第1-13章</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link is-active has-active" data-v-b05232f3 data-v-b05232f3><div class="item" data-v-b05232f3><div class="indicator" data-v-b05232f3></div><a class="VPLink link link" href="/blog/readingNotes/jsgc4-2.html" data-v-b05232f3 data-v-30c06bd3><!--[--><p class="text" data-v-b05232f3>第14-26章</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-93a960b4 data-v-0bd490fb><div class="VPDoc has-sidebar has-aside" data-v-0bd490fb data-v-c5936a1e><div class="container" data-v-c5936a1e><div class="aside" data-v-c5936a1e><div class="aside-curtain" data-v-c5936a1e></div><div class="aside-container" data-v-c5936a1e><div class="aside-content" data-v-c5936a1e><div class="VPDocAside" data-v-c5936a1e data-v-cdc66372><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-cdc66372 data-v-5dd9d5f6><div class="content" data-v-5dd9d5f6><div class="outline-marker" data-v-5dd9d5f6></div><div class="outline-title" data-v-5dd9d5f6>本页目录</div><nav aria-labelledby="doc-outline-aria-label" data-v-5dd9d5f6><span class="visually-hidden" id="doc-outline-aria-label" data-v-5dd9d5f6> Table of Contents for current page </span><ul class="root" data-v-5dd9d5f6 data-v-1188541a><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-cdc66372></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-c5936a1e><div class="content-container" data-v-c5936a1e><!--[--><!--]--><main class="main" data-v-c5936a1e><div style="position:relative;" class="vp-doc _blog_readingNotes_jsgc4-2" data-v-c5936a1e><div><p>JavaScript 高级程序设计第四版笔记第二部分</p><h2 id="_14-dom" tabindex="-1">14.DOM <a class="header-anchor" href="#_14-dom" aria-hidden="true">#</a></h2><h3 id="_14-1-节点层级" tabindex="-1">14.1 节点层级 <a class="header-anchor" href="#_14-1-节点层级" aria-hidden="true">#</a></h3><p><code>document</code>节点表示每个文档的根节点。根节点的唯一子节点是<code>&lt;html&gt;</code>元素，我们称之为<strong>文档元素</strong>（<code>documentElement</code>）。</p><h4 id="_14-1-2-文档子节点" tabindex="-1">14.1.2 文档子节点 <a class="header-anchor" href="#_14-1-2-文档子节点" aria-hidden="true">#</a></h4><p>文档只有一个子节点，即<code>&lt;html&gt;</code>元素。如下三个都指向 html 的引用：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> html </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">documentElement </span><span style="color:#676E95;font-style:italic;">// 取得对&lt;html&gt;的引用</span></span>
<span class="line"><span style="color:#A6ACCD;">html </span><span style="color:#89DDFF;">===</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">childNodes[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">] </span><span style="color:#676E95;font-style:italic;">// true</span></span>
<span class="line"><span style="color:#A6ACCD;">html </span><span style="color:#89DDFF;">===</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">firstChild </span><span style="color:#676E95;font-style:italic;">// true</span></span>
<span class="line"></span></code></pre></div><p>另外<code>document.body</code>可以方便的取得对<code>&lt;body&gt;</code>元素的引用。</p><h4 id="_14-1-4-text-类型" tabindex="-1">14.1.4 Text 类型 <a class="header-anchor" href="#_14-1-4-text-类型" aria-hidden="true">#</a></h4><p><code>text</code>节点中包含的文本可以通过<code>nodeValue</code>或<code>data</code>属性访问。</p><p>同时文本节点暴露了以下操作方法：</p><ul><li><p><code>appendData(text)</code>，向节点末尾追加文本 text</p></li><li><p><code>deleteData(offset,count)</code>从位置 offset 开始删除 count 个字符</p></li><li><p><code>insertData(offset,text)</code>、<code>replaceData(offset,count,text)</code>、<code>substringData(offset,count)</code>等等</p></li><li><p><code>document.createTextNode(text)</code>方法创建文本节点</p></li></ul><h3 id="_14-2-dom-编程" tabindex="-1">14.2 DOM 编程 <a class="header-anchor" href="#_14-2-dom-编程" aria-hidden="true">#</a></h3><p>通过<code>innerHTML</code>属性创建的<code>&lt;script&gt;</code>元素永远不会执行。</p><h3 id="_14-3-mutationobserver-接口" tabindex="-1">14.3 MutationObserver 接口 <a class="header-anchor" href="#_14-3-mutationobserver-接口" aria-hidden="true">#</a></h3><p><code>MutationObserver</code>接口可以在 DOM 被修改时异步执行回调，观察整个文档、DOM 树的一部分或某个元素。此外，还可以观察元素属性、子节点、文本或者前三者任意组合的变化。</p><p><code>MutationObserver</code>是为替代性能不好的<code>MutationEvent</code>而问世的。</p><h4 id="_14-3-1-基本用法" tabindex="-1">14.3.1 基本用法 <a class="header-anchor" href="#_14-3-1-基本用法" aria-hidden="true">#</a></h4><p>如下观察 body 元素属性变化的用例：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 新建一个实例</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> observer </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">MutationObserver</span><span style="color:#A6ACCD;">(</span><span style="color:#A6ACCD;font-style:italic;">mutationRecords</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">mutationRecords</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">body 属性发生了变化</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 执行observe方法</span></span>
<span class="line"><span style="color:#A6ACCD;">observer</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">observe</span><span style="color:#A6ACCD;">(document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">body</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">attributes</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 测试</span></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">body</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">className </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">test</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// [MutationRecord]</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// body 属性发生了变化</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 终止观察，这里放入setTimeout中，是为了上面的mutationRecords回调输出打印。</span></span>
<span class="line"><span style="color:#82AAFF;">setTimeout</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">observer</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">disconnect</span><span style="color:#F07178;">()</span></span>
<span class="line"><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><h2 id="_15-dom-扩展" tabindex="-1">15.DOM 扩展 <a class="header-anchor" href="#_15-dom-扩展" aria-hidden="true">#</a></h2><h3 id="_15-3-html5" tabindex="-1">15.3 HTML5 <a class="header-anchor" href="#_15-3-html5" aria-hidden="true">#</a></h3><h4 id="_15-3-2-焦点管理" tabindex="-1">15.3.2 焦点管理 <a class="header-anchor" href="#_15-3-2-焦点管理" aria-hidden="true">#</a></h4><p>HTML5 增加了附注 DOM 焦点管理的功能。</p><p><code>document.activeElement</code>始终包含当前拥有焦点的 DOM 元素。</p><p>默认情况下，页面刚加载完之后会设置为<code>document.body</code>，之后更改为通过 tab 键或 focus 方法让某个元素自动获得焦点。</p><p>另外<code>document.hasFocus()</code>方法返回布尔值，表示文档是否获得了焦点。比如在网页和 console 控制台互相切换，<code>document.hasFocus()</code>值就会变化。</p><p>是否有焦点元素<code>document.activeElement</code>和<code>document.hasFocus()</code>的值没什么关联。hasFocus 为 true 一定有焦点元素，有焦点元素不一定文档获得了焦点。</p><h4 id="_15-3-3-htmldocument-扩展" tabindex="-1">15.3.3 HTMLDOCUMENT 扩展 <a class="header-anchor" href="#_15-3-3-htmldocument-扩展" aria-hidden="true">#</a></h4><ul><li><p>readyState 属性</p><p>有两个之：</p><ul><li><code>loading</code>:表示文档正在加载</li><li><code>complete</code>:表示文档加载完成</li></ul><p>之前通常是通过<code>onload</code>事件来设置文档加载完成了的标记。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> (document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">readyState </span><span style="color:#89DDFF;">===</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">complete</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 执行操作</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div></li><li><p>head 属性</p></li></ul><p>作为对<code>document.body</code>的补充，HTML5 增加了<code>document.head</code>属性，指向文档的<code>&lt;head&gt;</code>元素。</p><h4 id="_15-3-5-自定义数据属性" tabindex="-1">15.3.5 自定义数据属性 <a class="header-anchor" href="#_15-3-5-自定义数据属性" aria-hidden="true">#</a></h4><p>非标准的自定义属性，使用前缀<code>data-</code>来定义。</p><p>可以通过元素的<code>dataset</code>属性来访问。</p><p>其中，<code>data-myname</code>和<code>data-myName</code>都通过<code>dataset.myname</code>来访问。</p><p><code>data-my-name</code>通过<code>dataset.myName</code>来访问。</p><h4 id="_15-3-7-scrollintoview" tabindex="-1">15.3.7 scrollIntoView <a class="header-anchor" href="#_15-3-7-scrollintoview" aria-hidden="true">#</a></h4><p><code>scrollIntoView(alignToTop,options)</code>方法可以滚动元素以便包含元素进入视口。</p><p>参数如下：</p><ul><li><code>alignToTop</code>:true 或 false，表示元素的顶部与视口顶部对齐，还是元素的底部与视口底部对齐</li><li><code>scrollIntoViewOptions</code>是一个对象： <ul><li><code>behavior</code>：过度动画，可取<code>smooth</code>、<code>auto</code>，默认是 auto</li><li><code>block</code>和<code>inline</code>，定义垂直与水平方向的对齐。</li></ul></li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">forms[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">scrollIntoView</span><span style="color:#A6ACCD;">(</span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">block</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">start</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">behavior</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">smooth</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><h3 id="_15-4-专有扩展" tabindex="-1">15.4 专有扩展 <a class="header-anchor" href="#_15-4-专有扩展" aria-hidden="true">#</a></h3><h4 id="_15-4-1-children-属性" tabindex="-1">15.4.1 children 属性 <a class="header-anchor" href="#_15-4-1-children-属性" aria-hidden="true">#</a></h4><p><code>children</code>属性是一个<code>HTMLCollection</code>，只包含元素的<code>Element</code>类型的节点。</p><p>而<code>childNodes</code>包括 Text、Comment 等其它类型节点。</p><h4 id="_15-4-2-contains-方法" tabindex="-1">15.4.2 contains 方法 <a class="header-anchor" href="#_15-4-2-contains-方法" aria-hidden="true">#</a></h4><p>判断传入元素是否调用元素的后代。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">documentElement</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">contains</span><span style="color:#A6ACCD;">(document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">body) </span><span style="color:#676E95;font-style:italic;">// true</span></span>
<span class="line"></span></code></pre></div><h4 id="_15-4-3-innertext-和-outertext" tabindex="-1">15.4.3 innerText 和 outerText <a class="header-anchor" href="#_15-4-3-innertext-和-outertext" aria-hidden="true">#</a></h4><p>返回对应元素的所有文本内容，虽然现代浏览器都支持这两个未入选 HTML5 标准的属性，但建议使用标准的<code>textContent</code>属性.</p><h4 id="_15-4-4-滚动" tabindex="-1">15.4.4 滚动 <a class="header-anchor" href="#_15-4-4-滚动" aria-hidden="true">#</a></h4><p><code>scrollIntoViewIfNeeded()</code>方法，在所有元素上可调用。它会在元素不可见的情况下，将其滚动到窗口或包含窗口中，如果已经在视口中可见，则什么都不做。 Safari、chrome 和 opera 实现了这个方法。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 如果元素不可见，则将元素可见。</span></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">images[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">scrollIntoViewIfNeeded</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"></span></code></pre></div><h2 id="_16-dom2-和-dom3" tabindex="-1">16.DOM2 和 DOM3 <a class="header-anchor" href="#_16-dom2-和-dom3" aria-hidden="true">#</a></h2><h3 id="_16-1-dom-的演进" tabindex="-1">16.1 DOM 的演进 <a class="header-anchor" href="#_16-1-dom-的演进" aria-hidden="true">#</a></h3><ul><li>内嵌窗格的变化</li></ul><p>DOM2 HTML 给<code>HTMLFrameElement</code>(即<code>&lt;iframe&gt;</code>)类型新增了一个<code>contentDocument</code>属性。 这个属性代表内嵌窗格中内容的<code>document</code>对象的指针。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> iframe </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myIframe</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> iframeDocument </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> iframe</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">contentDocument</span></span>
<span class="line"></span></code></pre></div><p>另外<code>contentWindow</code>属性是对应窗格的<code>window</code>对象。</p><blockquote><p><strong>注意</strong> 跨域访问内嵌窗格的<code>document</code>对象会受到安全限制。如果内嵌窗格中加载了不同域的页面，或者页面使用了不同协议，访问其<code>document</code>对象会抛出错误。</p></blockquote><h3 id="_16-2-样式" tabindex="-1">16.2 样式 <a class="header-anchor" href="#_16-2-样式" aria-hidden="true">#</a></h3><p>HTML 中样式有 3 种定义方式：</p><ul><li>外部样式表（通过<code>&lt;link&gt;</code>元素）</li><li>文档样式表（通过<code>&lt;style&gt;</code>元素）</li><li>元素特定样式（使用元素的<code>style</code>属性）。</li></ul><p>DOM2 Style 为这 3 种应用样式的机制都提供了 API</p><h4 id="_16-2-1-存取元素样式" tabindex="-1">16.2.1 存取元素样式 <a class="header-anchor" href="#_16-2-1-存取元素样式" aria-hidden="true">#</a></h4><p>大部分 HTML 元素在 Javascript 中都有一个对应的<code>style</code>属性，这个<code>style</code>属性是<code>CSSStyleDeclaration</code>类型的实例。它<strong>只包括通过<code>style</code>属性设置的所有样式</strong>，不包括外部样式表和文档样式表的样式。</p><p>css 属性名用连字符表示法表示的样式在 js 的 style 属性中会转换为驼峰大小形式（<code>background-iamge</code>--&gt;<code>backgroundImage</code>）</p><p>大多数属性能直接转换，但<code>float</code>不能，因为 float 是关键字，在 style 对象中应该是<code>cssFloat</code>。和 HTMLElement.className 表示 class 名称类似。</p><p>在标准模式下，所有尺寸都需要加上单位，不然会被忽略：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> myDiv </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">mhDiv</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">myDiv</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">width </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">100px</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">myDiv</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">height </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">100</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 无效</span></span>
<span class="line"></span></code></pre></div><ul><li>DOM 样式属性和方法 <ul><li><code>cssText</code>，包含 style 属性中的 css 代码</li><li><code>length</code>，应用给元素的 css 属性数量</li><li><code>getPropertyValue(propertyName)</code>，返回属性<code>propertyName</code>的字符串值</li><li><code>removeProperty(propertyName)</code>从样式中删除 css 属性<code>propertyName</code></li><li><code>setProperty(propertyName,value,priority)</code>，设置一个属性的值，priority 是<code>important</code>或空字符串</li></ul></li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> temp1 </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">mydiv</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">temp1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">setProperty</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">line-height</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1.5</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">temp1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getPropertyValue</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">line-height</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// &quot;1.5&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">temp1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">line-height</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">] </span><span style="color:#676E95;font-style:italic;">// &quot;1.5&quot;</span></span>
<span class="line"></span></code></pre></div><ul><li>计算样式</li></ul><p><code>style</code>对象包含 style 属性上设置的样式，但不包含其它地方同样影响该元素的样式信息。</p><p>DOM2 style 在<code>document.defaultView</code>上增加了<code>getComputedStyle()</code>方法。它接受 2 个参数：要取得计算样式的元素和伪元素字符串（如:<code>&quot;:after&quot;</code>）。如果不需要查询伪元素，可传 null。该方法返回一个和 style 对象一样的<code>CSSStyleDeclaration</code>对象，包含元素的计算样式。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> myDiv </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myDiv</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> computedStyle </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">defaultView</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getComputedStyle</span><span style="color:#A6ACCD;">(myDiv</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">null</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(computedStyle</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">width) </span><span style="color:#676E95;font-style:italic;">// 100px</span></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(computedStyle</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">color) </span><span style="color:#676E95;font-style:italic;">// rgb(17,17,17)</span></span>
<span class="line"></span></code></pre></div><blockquote><p><strong>注意</strong> 所有计算样式都是只读的，不能修改<code>getComputedStyle()</code>方法返回的对象，修改请用<code>style</code>对象。而且，计算样式还包括浏览器内部样式表中的信息，即所有有默认值的 css 属性会出现在计算样式里。</p></blockquote><h4 id="_16-2-2-操作样式表" tabindex="-1">16.2.2 操作样式表 <a class="header-anchor" href="#_16-2-2-操作样式表" aria-hidden="true">#</a></h4><p><code>CSSStyleSheet</code>类型表示 css 样式表，包括使用<code>&lt;link&gt;</code>元素和<code>&lt;style&gt;</code>元素定义的样式信息。</p><p><code>CSSStyleSheet</code>类型的实例是一个只读对象（<code>disabled</code>除外）。</p><p><code>CSSStyleSheet</code>继承自<code>StyleSheet</code></p><p><code>document.styleSheets</code>表示文档中可用样式表集合,由 n 条<code>styleSheet</code>对象组成，页面有多少个<code>&lt;link ref=&quot;stylesheet&quot;&gt;</code>和<code>&lt;style&gt;</code>元素，则<code>document.styleSheets.length</code>就是多少。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> sheet </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">null</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> (</span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> i </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> len </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">styleSheets</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">length</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> i </span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;"> len</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> i</span><span style="color:#89DDFF;">++</span><span style="color:#A6ACCD;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">sheet</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">styleSheets</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">i</span><span style="color:#F07178;">]</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">sheet</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">href</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p><code>styleSheet</code>长下面这样：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">cssRules</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">CSSRuleList</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F78C6C;">0</span><span style="color:#F07178;">: </span><span style="color:#A6ACCD;">CSSStyleRule</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">: </span><span style="color:#A6ACCD;">CSSStyleRule</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">2</span><span style="color:#F07178;">:  …</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">disabled</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">false</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">href</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">https://www.ituring.com.cn/kendo/css?v=W-IyudFsjvr8DmczNaEtVDAWVVWkoAYhOkQl_7kkbqc1</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">media</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">MediaList</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#FFCB6B;">mediaText</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">length</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">ownerNode</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">link</span><span style="color:#F07178;">#</span><span style="color:#A6ACCD;">myCss</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">ownerRule</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">parentStyleSheet</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">title</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">type</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/css</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><ul><li><p>css 规则</p><p>其中<code>cssRules</code>就是样式规则集合，由 n 条<code>CSSStyleRule</code>组成，<code>CSSStyleRule</code>长这样：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">cssText</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">.fake { color: red; }</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">parentRule</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">parentStyleSheet</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">CSSStyleSheet</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#FFCB6B;">ownerRule</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">cssRules</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">CSSRuleList</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">rules</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">CSSRuleList</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">type</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/css</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">href</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">https://www.ituring.com.cn/kendo/css?v=W-IyudFsjvr8DmczNaEtVDAWVVWkoAYhOkQl_7kkbqc1</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> …</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">selectorText</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">.fake</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">style</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">CSSStyleDeclaration</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F78C6C;">0</span><span style="color:#F07178;">: </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">color</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">alignContent</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">alignItems</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">alignSelf</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">alignmentBaseline</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">all</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> …</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">styleMap</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">StylePropertyMap</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#FFCB6B;">size</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#FFCB6B;">type</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>从上面可以看出，<code>cssText</code>是该条规则的完整文本输出（和<code>HTMLElement.style.cssText</code>类似，但前者是只读的），<code>selectorText</code>则是选择符文本，<code>style</code>则是熟悉的<code>CSSStyleDeclaration</code>对象，是<strong>可修改的</strong>。</p><p>另外，通过<code>&lt;link&gt;</code>或<code>&lt;style&gt;</code>元素也可以直接获取<code>CSSStyleSheet</code>对象。DOM 在这两个元素上暴露了<code>sheet</code>属性。</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">link</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">id</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myCss</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">href</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/kendo/css?v=W-IyudFsjvr8DmczNaEtVDAWVVWkoAYhOkQl_7kkbqc1</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">rel</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">stylesheet</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> css </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">myCss</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">css</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sheet </span><span style="color:#676E95;font-style:italic;">// CSSStyleSheet</span></span>
<span class="line"><span style="color:#A6ACCD;">css</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sheet</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">href </span><span style="color:#676E95;font-style:italic;">// &quot;https://www.ituring.com.cn/kendo/css?v=W-IyudFsjvr8DmczNaEtVDAWVVWkoAYhOkQl_7kkbqc1&quot;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span></code></pre></div></li><li><p>创建规则</p><p>可使用<code>insertRule()</code>方法向样式表中添加新规则。它接受 2 个参数：规则文本和插入位置的索引。</p><p>如下是添加一个背景，并删除的示例。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> style </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">createElement</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">style</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 创建style元素</span></span>
<span class="line"><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">type </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/css</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">head</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">appendChild</span><span style="color:#A6ACCD;">(style) </span><span style="color:#676E95;font-style:italic;">// 先插入到文档中，才能使用sheet</span></span>
<span class="line"><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sheet</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">insertRule</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">body{background:silver}</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 插入即生效</span></span>
<span class="line"><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sheet</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">deleteRule</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 删除对应索引位置的规则。</span></span>
<span class="line"></span></code></pre></div></li><li><p>删除规则</p><p>上面已经演示过了，即<code>deleteRule(index)</code>方法。</p></li></ul><h4 id="_16-2-3-元素尺寸" tabindex="-1">16.2.3 元素尺寸 <a class="header-anchor" href="#_16-2-3-元素尺寸" aria-hidden="true">#</a></h4><p>本节介绍的属性和方法不在 DOM2 style 规范中，但都已在所有主流浏览器实现。</p><p>下面分别从<strong>偏移尺寸</strong>、<strong>客户端尺寸</strong>、<strong>滚动尺寸</strong>3 个方面来说。</p><ul><li><p>偏移尺寸</p><p>偏移尺寸包含元素在屏幕上占用的所有视觉空间。元素在页面上的视觉空间由其高度和宽度决定，包括所有的内边距、滚动条和边框，不包含外边距。</p><p>下面 4 个属性用于取得元素的偏移尺寸：</p><ul><li><code>offsetHeight</code>，元素在垂直方向上占用的像素尺寸，包括它的高度、水平滚动条的高度和上下边框的高度。</li><li><code>offsetLeft</code>，元素左边框外侧距离包含元素左边框内侧的像素数</li><li><code>offsetTop</code>，元素上边框外侧距离包含元素上边框内侧的像素</li><li><code>offsetWidth</code>，元素在水平方向上占用的像素，包括它的宽度、垂直滚动条和左右边框的宽度。</li><li>如下图： <img src="/assets/2.f74fa688.png" alt="偏移尺寸示意"></li></ul><blockquote><p><strong>注意</strong> 所有这些属性都是只读的，每次访问都会重新计算。因此尽量减少查询它们的次数。最好保存在局部变量中。</p></blockquote></li><li><p>客户端尺寸</p><p><strong>客户端尺寸</strong>包含元素内容及其内边距所占用的空间。只有两个属性：<code>clientWidth</code>和<code>clientHeight</code>。 其中<code>clientWidth</code>是内容区宽度加左、右内边距宽度， <code>clientHeight</code>是内容区高度加上、下内边距高度。</p><p>客户端尺寸其实就是元素可视区域的空间，不包含滚动条和边框。 经常用<code>document.documentElement</code>的<code>clientWidth</code>和<code>clientHeight</code>这俩个属性表示视口(<code>&lt;html&gt;或&lt;body&gt;</code>)的尺寸。</p></li></ul><ul><li><p>滚动尺寸</p><p>滚动尺寸相关的属性有 4 个：</p><ul><li><code>scrollHeight</code>,没有滚动条出现时，元素内容的总高度。</li><li><code>scrollLeft</code>，内容区左侧隐藏的像素数，可设置</li><li><code>scrollTop</code>，内容区顶部隐藏的像素数，可设置后改变滚动元素的位置</li><li><code>scrollWidth</code>，没有滚动条出现时元素内容的总宽度</li></ul><p><strong>以下重点</strong>：</p><p><code>scrollWidth,scrollHeight</code>和<code>clientWidth,clientHeight</code>之间的关系在不需要滚动条的文档上是分不清的（相等）。如果文档尺寸超过视口尺寸，则<code>scrollHeight,scrollHeight</code>等于文档内容实际的宽高，而<code>clientWidth,clientHeight</code>等于视口（可见区域）的大小</p><p>如下示例，box 的<code>scrollHeight</code>为 600，<code>clientHeight</code>为 300；child 的<code>scrollHeight</code>和<code>clientHeight</code>相等都为 600。</p><div class="language-html"><button title="Copy Code" class="copy"></button><span class="lang">html</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FFCB6B;">svg</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#B2CCD6;">border</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1px</span><span style="color:#A6ACCD;"> solid black</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">.</span><span style="color:#FFCB6B;">box</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#B2CCD6;">height</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">300px</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#B2CCD6;">overflow</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> auto</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#B2CCD6;">border</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1px</span><span style="color:#A6ACCD;"> solid red</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">.</span><span style="color:#FFCB6B;">child</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#B2CCD6;">height</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">600px</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">body</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">class</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">box</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">class</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">child</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">child</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">body</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span></code></pre></div></li></ul><ul><li><p>确定元素尺寸</p><p>浏览器在每个元素上都暴露了<code>getBoundingClientRect()</code>方法，返回一个<code>DOMRect</code>对象。包含 6 个属性：<code>left,top,right,bottom,height,width</code>，这些属性给出了元素在页面中<strong>相对于视口的位置</strong>。</p><p>其中<code>bottom</code>和<code>right</code>分别是元素底部距离视口顶部的距离、元素最右侧距离视口左侧的距离。</p><p>其中<code>width</code>和<code>height</code>属性是包括滚动条和边框版的<code>clientWidth</code>和<code>clientHeight</code>。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 还是用上面示例来计算</span></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementsByClassName</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">box</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getBoundingClientRect</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// {x: 8, y: 8, width: 737, height: 302, top: 8,left:8,right:745,bottom:310}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementsByClassName</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">child</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getBoundingClientRect</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// {x: 9, y: 9, width: 718, height: 600, top: 9,...}</span></span>
<span class="line"></span></code></pre></div></li></ul><h3 id="_16-4-范围" tabindex="-1">16.4 范围 <a class="header-anchor" href="#_16-4-范围" aria-hidden="true">#</a></h3><p>范围在常规 DOM 操作的粒度不够时可以发挥作用。</p><h2 id="_17-事件" tabindex="-1">17 事件 <a class="header-anchor" href="#_17-事件" aria-hidden="true">#</a></h2><h3 id="_17-1-事件流" tabindex="-1">17.1 事件流 <a class="header-anchor" href="#_17-1-事件流" aria-hidden="true">#</a></h3><p><strong>事件冒泡</strong>，事件从最具体的元素开始触发，然后向上传播，直到<code>document</code>。现代浏览器会一直冒泡到<code>window</code>对象</p><p><strong>事件捕获</strong>，事件从<code>document</code>开始到最具体的元素。</p><p>由于旧版浏览器不支持，因此通常建议使用事件冒泡。</p><h4 id="_17-1-3-dom-事件流" tabindex="-1">17.1.3 DOM 事件流 <a class="header-anchor" href="#_17-1-3-dom-事件流" aria-hidden="true">#</a></h4><p>DOM2Events 规范规定事件流分为 3 个阶段：事件捕获、到达目标和事件冒泡。</p><p>虽然规范中事件捕获不会发生在目标元素上，但在现代浏览器实现中，事件捕获会在目标上触发，所以目标元素有两次机会触发事件。</p><h3 id="_17-2-事件处理程序" tabindex="-1">17.2 事件处理程序 <a class="header-anchor" href="#_17-2-事件处理程序" aria-hidden="true">#</a></h3><p>事件处理程序是为响应事件而调用的函数。一般有 3 中事件处理方式。</p><h4 id="_17-2-1-html-属性方式" tabindex="-1">17.2.1 HTML 属性方式 <a class="header-anchor" href="#_17-2-1-html-属性方式" aria-hidden="true">#</a></h4><p>给事件属性的值指定能直接执行的 JavaScript 字符串代码。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  function showMessage() </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Hello world!</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">input</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">type</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">button</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">value</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Click Me</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onclick</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">showMessage()</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">/&gt;</span></span>
<span class="line"></span></code></pre></div><h4 id="_17-2-2-dom0-事件处理程序" tabindex="-1">17.2.2 DOM0 事件处理程序 <a class="header-anchor" href="#_17-2-2-dom0-事件处理程序" aria-hidden="true">#</a></h4><p>每个元素（包括<code>window</code>和<code>document</code>）都有小写的事件处理程序属性，比如<code>onclick</code>。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> btn </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myBtn</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">btn</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onclick</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">clicked</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h4 id="_17-2-3-dom2-事件处理程序" tabindex="-1">17.2.3 DOM2 事件处理程序 <a class="header-anchor" href="#_17-2-3-dom2-事件处理程序" aria-hidden="true">#</a></h4><p>主要通过<code>addEventListener()</code>和<code>removeEventListener()</code>来实现。 它们接受 3 个参数：事件名、事件处理函数和是否在捕获阶段调用事件处理程序（默认 false）。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> btn </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myBtn</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handler</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">id</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">btn</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">click</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> handler</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 监听点击事件</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// ...其它逻辑</span></span>
<span class="line"><span style="color:#A6ACCD;">btn</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">removeEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">click</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> handler</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 取消监听</span></span>
<span class="line"></span></code></pre></div><h3 id="_17-3-事件对象" tabindex="-1">17.3 事件对象 <a class="header-anchor" href="#_17-3-事件对象" aria-hidden="true">#</a></h3><p>DOM 事件发生时，所有相关信息都会被收集并存储在一个名为<code>event</code>的对象中。</p><p><code>event</code>对象有一些属性，其中<code>target</code>是事件真正目标元素，<code>currentTarget</code>是注册事件处理程序的元素。例如我点击 button，然后在 document.body 上注册点击事件处理程序，那么此时 target 为 button，currentTarget 为 body。</p><h3 id="_17-4-事件类型" tabindex="-1">17.4 事件类型 <a class="header-anchor" href="#_17-4-事件类型" aria-hidden="true">#</a></h3><h4 id="_17-4-3-鼠标和滚轮事件" tabindex="-1">17.4.3 鼠标和滚轮事件 <a class="header-anchor" href="#_17-4-3-鼠标和滚轮事件" aria-hidden="true">#</a></h4><ul><li><p><strong>客户端坐标</strong></p><p>鼠标事件都是在浏览器视口中的某个位置上发生的。这些信息被保存在<code>event</code>对象的<code>clientX</code>和<code>clientY</code>属性中。表示事件发生时鼠标光标在视口中的坐标，所有浏览器都支持。</p></li><li><p><strong>页面坐标</strong></p><p>页面坐标是事件发生时鼠标光标在页面上的坐标，通过<code>event</code>对象的<code>pageX</code>和<code>pageY</code>获取，表示鼠标光标在页面上的位置。</p><p>在页面没有滚动时，<code>pageX,pageY</code>与<code>clientX,clientY</code>的值相同</p></li><li><p><strong>屏幕坐标</strong></p><p>可以通过<code>event</code>对象的<code>screenX,screenY</code>属性获取鼠标光标在屏幕上的坐标。</p></li></ul><h4 id="_17-4-4-键盘与输入事件" tabindex="-1">17.4.4 键盘与输入事件 <a class="header-anchor" href="#_17-4-4-键盘与输入事件" aria-hidden="true">#</a></h4><p>键盘事件包含 3 个事件：</p><ul><li><code>keydown</code>,用户按下键盘上某个键时触发，而且持续按住会重复触发。</li><li><code>keypress</code>,用户按下键盘上某个键并产生字符时触发，而且持续按住会重复触发。Esc 键也会触发。DOM3 Events 废弃了该事件，推荐用<code>textInput</code>事件</li><li><code>keyup</code>，用户释放键盘上某个键时触发</li><li><code>textInput</code>，<code>keypress</code>的扩展，用于在文本显示给用户之前触发。</li></ul><h4 id="_17-4-7-html5-事件" tabindex="-1">17.4.7 HTML5 事件 <a class="header-anchor" href="#_17-4-7-html5-事件" aria-hidden="true">#</a></h4><ul><li><p><code>contextmenu</code> 事件</p><p>常用作右键菜单。</p></li><li><p><code>beforeunload</code> 事件</p><p>这个事件会在页面即将从浏览器中卸载时触发。</p></li><li><p><code>DOMContentLoaded</code>事件</p><p>该事件会在 DOM 树构建完成后立即触发，而不用等待图片、JavaScript 文件、css 文件或其它资源加载完成，会比<code>load</code>事件先发生。而<code>load</code>事件是要等待这些资源加载完成，会花较长时间。</p></li><li><p><code>hashchange</code>事件</p><p>当 URL 散列值（URL#后面的部分）发生变化时触发。该事件必须添加给<code>window</code>。<code>event</code>对象有两个新属性：<code>oldURL</code>和<code>newURL</code>。</p></li></ul><h3 id="_17-5-内存与性能" tabindex="-1">17.5 内存与性能 <a class="header-anchor" href="#_17-5-内存与性能" aria-hidden="true">#</a></h3><h4 id="_17-5-1-事件委托" tabindex="-1">17.5.1 事件委托 <a class="header-anchor" href="#_17-5-1-事件委托" aria-hidden="true">#</a></h4><p>过多的事件处理程序会占用更多内存，性能会越来越差，解决方案是使用<strong>事件委托</strong>。</p><h3 id="_17-6-模拟事件" tabindex="-1">17.6 模拟事件 <a class="header-anchor" href="#_17-6-模拟事件" aria-hidden="true">#</a></h3><h4 id="_17-6-1-dom-事件模拟" tabindex="-1">17.6.1 DOM 事件模拟 <a class="header-anchor" href="#_17-6-1-dom-事件模拟" aria-hidden="true">#</a></h4><ul><li><p>模拟鼠标事件</p><p>基本类似如下：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> btn </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myBtn</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> me </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">createEvent</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">MouseEvents</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">me</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">initMouseEvent</span><span style="color:#A6ACCD;">(</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">click</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 触发类型</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 是否冒泡</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 是否可取消</span></span>
<span class="line"><span style="color:#A6ACCD;">  document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">defaultView</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 与事件关联的视图，基本是document.defaultView</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">null</span></span>
<span class="line"><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">btn</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">dispatchEvent</span><span style="color:#A6ACCD;">(me)</span></span>
<span class="line"></span></code></pre></div></li><li><p>2.模拟键盘事件</p><p>例子如下,模拟的是按住 Shift 的同时又按下 A 键：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">var</span><span style="color:#A6ACCD;"> textbox </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myTextbox</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  event</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//以DOM3级方式创建事件对象</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> (document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">implementation</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">hasFeature</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">KeyboardEvents</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">3.0</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">event</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">crateEvent</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">KeyboardEvent</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">//初始化事件对象</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">event</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">initKeyboardEvent</span><span style="color:#F07178;">(</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">keydown</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">defaultView</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 按下按键的字符串代码</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// location，按下的位置，0默认</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Shift</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 修饰键列表，多个由空格分隔</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#F78C6C;">0</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 连续按了这个键多少次</span></span>
<span class="line"><span style="color:#F07178;">  )</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//触发事件</span></span>
<span class="line"><span style="color:#A6ACCD;">textbox</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">dispatchEvent</span><span style="color:#A6ACCD;">(event)</span></span>
<span class="line"></span></code></pre></div></li><li><p>3.自定义 DOM 事件</p><p>DOM3 级定义了“自定义事件”，自定义事件不是由原生触发的，由开发人员自己创建自己的事件</p><p>调用<code>createEvent(&quot;CustomEvent&quot;)</code>，返回的对象有一个名为<code>initCustomEvent()</code>的方法，接受四个参数：</p><ul><li>type：触发的时间类型，字符串，例如“keydown”</li><li>bubbles：布尔值，表示事件是否应该冒泡</li><li>cancelable：布尔值，表示事件是否可以取消</li><li>detail：对象，任意值，保存在 event 对象的 detail 属性中。</li></ul><p>示例如下，创建一个自定义的名字叫 myEvent 的事件：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">var</span><span style="color:#A6ACCD;"> myDiv </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myDiv</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//先监听一下：</span></span>
<span class="line"><span style="color:#A6ACCD;">window</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myEvent</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">detail</span><span style="color:#F07178;">) </span><span style="color:#676E95;font-style:italic;">//{name:&quot;huyu&quot;,age:88}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#FF9CAC;">false</span></span>
<span class="line"><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#C792EA;">var</span><span style="color:#A6ACCD;"> event </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">createEvent</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">CustomEvent</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">event</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">initCustomEvent</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myEvent</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">huyu</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">age</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">88</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//让div触发事件</span></span>
<span class="line"><span style="color:#A6ACCD;">myDiv</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">dispatchEvent</span><span style="color:#A6ACCD;">(event)</span></span>
<span class="line"></span></code></pre></div></li></ul><h2 id="_18-动画与-canvas-图形" tabindex="-1">18 动画与 canvas 图形 <a class="header-anchor" href="#_18-动画与-canvas-图形" aria-hidden="true">#</a></h2><h3 id="_18-1-使用-requestanimationframe" tabindex="-1">18.1 使用 requestAnimationFrame <a class="header-anchor" href="#_18-1-使用-requestanimationframe" aria-hidden="true">#</a></h3><p>一般计算机显示器的屏幕刷新率都是 60Hz，基本上每秒需要重绘 60 次。</p><p>因此，要实现平滑动画，最佳的重绘时间间隔为 1000 毫秒/60，即 17 毫秒。</p><p>无论<code>setInterval()</code>还是<code>setTimout()</code>都不能保证时间精度，第二个参数的延时只能保证<strong>何时会把代码添加到浏览器的任务队列</strong>，<strong>不能保证</strong>添加到队列就会立即运行。</p><p>下面是简单的使用示例：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> div </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">status</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">updateProgress</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">div</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">width</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">parseInt</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">div</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">width</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">10</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">5</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">%</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">div</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">style</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">left</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">!==</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">100%</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">window</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">requestAnimationFrame</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">updateProgress</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> requestID </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> window</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">requestAnimationFrame</span><span style="color:#A6ACCD;">(updateProgress)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 取消</span></span>
<span class="line"><span style="color:#A6ACCD;">window</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">cancelAnimationFrame</span><span style="color:#A6ACCD;">(requestID)</span></span>
<span class="line"></span></code></pre></div><h2 id="_19-表单脚本" tabindex="-1">19 表单脚本 <a class="header-anchor" href="#_19-表单脚本" aria-hidden="true">#</a></h2><h3 id="_19-1-表单基础" tabindex="-1">19.1 表单基础 <a class="header-anchor" href="#_19-1-表单基础" aria-hidden="true">#</a></h3><h4 id="_19-1-3-表单字段" tabindex="-1">19.1.3 表单字段 <a class="header-anchor" href="#_19-1-3-表单字段" aria-hidden="true">#</a></h4><ul><li>表单字段公共事件</li></ul><p><code>change</code>:在<code>&lt;input&gt;</code>和<code>&lt;textarea&gt;</code>元素的<code>value</code>发生变化<strong>且失去焦点</strong>时触发。或者在<code>&lt;select&gt;</code>元素中选中项发生变化时触发。</p><h3 id="_19-2-文本框编程" tabindex="-1">19.2 文本框编程 <a class="header-anchor" href="#_19-2-文本框编程" aria-hidden="true">#</a></h3><h4 id="_19-2-1-选择文本" tabindex="-1">19.2.1 选择文本 <a class="header-anchor" href="#_19-2-1-选择文本" aria-hidden="true">#</a></h4><ul><li><p><code>select()</code>方法</p><p><code>&lt;input&gt;</code>和<code>&lt;textarea&gt;</code>都支持<code>select()</code>方法，用于全部选中文本框中的文本。一般用作默认获得焦点时全部选中文本，提升体验。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">textbox</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">foucs</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">select</span><span style="color:#F07178;">()</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div></li><li><p>部分选中文本</p><p><code>setSelectionRange()</code>方法接受两个参数：要选择的第一个字符的索引和停止选择的字符的索引。</p><p>注意在调用此方法前或后给文本框设置焦点。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">textbox</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">focus</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">textbox</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">setSelectionRange</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> textbox</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">length) </span><span style="color:#676E95;font-style:italic;">// 选择所有文本</span></span>
<span class="line"></span></code></pre></div></li></ul><h4 id="_19-2-2-输入过滤" tabindex="-1">19.2.2 输入过滤 <a class="header-anchor" href="#_19-2-2-输入过滤" aria-hidden="true">#</a></h4><ul><li><p>屏蔽字符</p><p>可以通过<code>keypress</code>事件来屏蔽特定字符，如下让输入框只能输入数字：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">textbox</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">keypress</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">!</span><span style="color:#89DDFF;">/</span><span style="color:#C3E88D;">\d</span><span style="color:#89DDFF;">/</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">test</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">String</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">fromCharCode</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">charCode</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">&amp;&amp;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">!</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">ctrlKey</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 不屏蔽ctrl键</span></span>
<span class="line"><span style="color:#F07178;">  ) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">preventDefault</span><span style="color:#F07178;">() </span><span style="color:#676E95;font-style:italic;">// 阻止默认行为，及防止字符给输入框</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div></li><li><p>处理剪贴板</p><p>在复制、剪切、粘贴操作，浏览器也提供了一些事件来让我们操作，如下是在复制时，设置剪贴板的值：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">copy</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">clipboardData</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">setData</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/plain</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">不同要i复制i2</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">preventDefault</span><span style="color:#F07178;">() </span><span style="color:#676E95;font-style:italic;">// 阻止默认复制操作，以使用setData的值</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div></li></ul><h3 id="_19-4-表单序列化" tabindex="-1">19.4 表单序列化 <a class="header-anchor" href="#_19-4-表单序列化" aria-hidden="true">#</a></h3><p>表单序列化（form serialization）将表单字段的<code>name</code>和<code>value</code>属性进行序列化。</p><p>禁用字段不会发送到服务器。</p><h3 id="_19-5-富文本编辑" tabindex="-1">19.5 富文本编辑 <a class="header-anchor" href="#_19-5-富文本编辑" aria-hidden="true">#</a></h3><h4 id="_19-5-2-与富文本交互" tabindex="-1">19.5.2 与富文本交互 <a class="header-anchor" href="#_19-5-2-与富文本交互" aria-hidden="true">#</a></h4><p>主要使用<code>document.execCommand()</code>方法，它接受三个参数：要执行的命令、浏览器是否为命令提供用户界面的布尔值和执行命令必需的值。一般第二个参数是 false。</p><p>如下复制已选中文本：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">execCommand</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">copy</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">null</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><h2 id="_20-javascript-api" tabindex="-1">20 Javascript API <a class="header-anchor" href="#_20-javascript-api" aria-hidden="true">#</a></h2><h3 id="_20-2-跨上下文消息" tabindex="-1">20.2 跨上下文消息 <a class="header-anchor" href="#_20-2-跨上下文消息" aria-hidden="true">#</a></h3><p><strong>跨文档消息</strong>(XDM cross-document messaging)主要用于不同窗口(iframe)直接通信或工作线程(worker)之间通信</p><p>XDM 的核心是<code>postMessage()</code>方法和<code>message</code>事件。</p><p>以下以一个主页面和嵌入页面的交流示例：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 主页面 http://example.com</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> contentWindow </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">myIframe</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">contentWindow</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">contentWindow</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">postMessage</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hello example.org</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">http://example.org</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 嵌入主页面的iframe http://example.org</span></span>
<span class="line"><span style="color:#A6ACCD;">window</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">message</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 检查消息来源</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">origin</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">===</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">http://example.com</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">data</span><span style="color:#F07178;">) </span><span style="color:#676E95;font-style:italic;">// hello example.org</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 回复消息</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">source</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">postMessage</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">yes, received</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">http://example.com</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><p>总之，在通过 iframe 加载不同域或同域的页面时，使用 XDM 交流还是非常方便的。</p><h3 id="_20-4-file-api-和-blob-api" tabindex="-1">20.4 File API 和 Blob API <a class="header-anchor" href="#_20-4-file-api-和-blob-api" aria-hidden="true">#</a></h3><h4 id="_20-4-1-file-类型" tabindex="-1">20.4.1 File 类型 <a class="header-anchor" href="#_20-4-1-file-类型" aria-hidden="true">#</a></h4><p>File 类型一般用在表单中的文件输入字读，文件输入字段会在文件变化时添加<code>files</code>集合，此集合会包含一组<code>File</code>对象，每个<code>File</code>对象都有一些只读属性：</p><ul><li><code>name</code>:本地系统中的文件名</li><li><code>size</code>:以字节为单位的文件大小</li><li><code>type</code>:包含文件 MIME 类型的字符串</li></ul><p>如下示例：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// html: &lt;input id=&quot;input&quot; type=&quot;file&quot; /&gt;</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> input </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">input</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">change</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#F07178;"> (</span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">of</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">files</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><p>注意 file 输入框 change 事件多次选择同一个文件是不会触发的，需要不同文件。</p><h4 id="_20-4-2-filereader-类型" tabindex="-1">20.4.2 FileReader 类型 <a class="header-anchor" href="#_20-4-2-filereader-类型" aria-hidden="true">#</a></h4><p><code>FileReader</code>类型表示一种异步文件读取机制，让我们可以从文件中读取数据。</p><p><code>FileReader</code>类型提供了几个读取文件数据的方法：</p><ul><li><code>readAdText(file,encoding)</code>:从文件中读取纯文本内容并保存在<code>result</code>属性中，第二个参数标识编码，可选。</li><li><code>readAsDataURL(file)</code>:读取文件并将内容的数据 URI 保存在<code>result</code>属性中</li><li><code>readAsBinaryString(file)</code>:读取文件并将每个字符的二进制数据保存在<code>result</code>属性中</li><li><code>radAsArrayBuffer(file)</code>:读取文件并将文件内容以<code>ArrayBuffer</code>形式保存在<code>result</code>属性</li></ul><p>这些方法为处理文件提供了极大灵活性，比如为了显示图片，可以将图片文件读取为 URI，为了解析文本内容，可以读取为文本。</p><p>读取是异步的，每个<code>FileReader</code>会发布 3 个有用的事件<code>progress</code>、<code>error</code>、<code>load</code>，分别表示还有更多数据、发生了错误和读取完成。</p><p>发生<code>error</code>事件时，<code>FileReader</code>实例会有一个 error 属性对象包含错误信息，它有一个<code>code</code>属性，值可能时 1(未找到文件)、2（安全错误）、3（读取中断）、4（文件不可读）或 5（编码错误）。</p><p>下面是一个读取文件内容实例：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// html: &lt;input id=&quot;input&quot; type=&quot;file&quot; /&gt;</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> input </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">input</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">change</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#F07178;"> (</span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">of</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">files</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">readFile</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">readFile</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">file</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">instanceof</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">File</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">reader</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">FileReader</span><span style="color:#F07178;">()</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">readAsText</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onload</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">文件内容：</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">result</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onprogress</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">lengthComputable</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">读取进度</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">loaded </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;"> e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">total</span><span style="color:#89DDFF;">}`</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onerror</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">错误</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">error</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">code</span><span style="color:#89DDFF;">}`</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h4 id="_20-4-3-filereadersync-类型" tabindex="-1">20.4.3 FileReaderSync 类型 <a class="header-anchor" href="#_20-4-3-filereadersync-类型" aria-hidden="true">#</a></h4><p><code>FileReaderSync</code>是<code>FileReader</code>的同步版，只在工作线程中(worker)可用，因为文件太大读取时间太长会影响全局。</p><h4 id="_20-4-4-blob-与部分读取" tabindex="-1">20.4.4 Blob 与部分读取 <a class="header-anchor" href="#_20-4-4-blob-与部分读取" aria-hidden="true">#</a></h4><p>某些情况我们可能只想读取部分文件而不是全部文件，为此<code>File</code>对象提供了一个<code>slice()</code>方法，接受 2 个参数：起始字节和要读取的字节数。它返回一个<code>Blob</code>实例，<code>Blob</code>实际上是<code>File</code>的超类。</p><p><code>FileReader</code>可以从<code>Blob</code>中读取数据, 下面的是上面的例子的修改：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight has-highlighted-lines" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> input </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">input</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">change</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#F07178;"> (</span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">of</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">files</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">readFile</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">readFile</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">file</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">instanceof</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">File</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 读取前12个字节</span></span>
<span class="line highlighted"><span style="color:#F07178;">    </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">blob</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">file</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">slice</span><span style="color:#F07178;">(</span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">12</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">reader</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">FileReader</span><span style="color:#F07178;">()</span></span>
<span class="line highlighted"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">readAsText</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">blob</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onload</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">文件内容：</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">result</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onprogress</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">lengthComputable</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">读取进度</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">loaded </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;"> e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">total</span><span style="color:#89DDFF;">}`</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onerror</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">错误</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">reader</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">error</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">code</span><span style="color:#89DDFF;">}`</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h4 id="_20-4-5-对象-url-与-blob" tabindex="-1">20.4.5 对象 URL 与 Blob <a class="header-anchor" href="#_20-4-5-对象-url-与-blob" aria-hidden="true">#</a></h4><p>对象 URL 也称作 Blob URL，是指引用存储在<code>File</code>或<code>Blob</code>中数据的 URL。它的优点是不用把文件内容读取到 Javascript 也可以使用文件。</p><ul><li>创建对象 URL</li></ul><p>要创建对象 URL，可以使用<code>window.URL.createObjectURL()</code>方法并传入<code>File</code>或<code>Blob</code>对象。这个方法的返回值是一个指向内存地址的字符串。因为这个字符串是 URL，所以可以在 DOM 中直接使用。</p><p>另外在使用完数据后，最好使用<code>window.URL.revokeObjectURL()</code>方法释放内存。</p><p>如下选择图片时可预览图片：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// &lt;input placeholder=&quot;请输入&quot; id=&quot;input&quot; type=&quot;file&quot; /&gt;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// &lt;img src=&quot;&quot; id=&quot;img&quot; /&gt;</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> input </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">input</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> img </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">img</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">input</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">change</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">e</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#F07178;"> (</span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">of</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">files</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">showImg</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">showImg</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">file</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">/</span><span style="color:#C3E88D;">image</span><span style="color:#89DDFF;">/</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">test</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">type</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">url</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">window</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">URL</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">createObjectURL</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">file</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">img</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">setAttribute</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">src</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">url</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// window.URL.revokeObjectURL(url) // 在不使用时执行</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h4 id="_20-4-6-读取拖放文件" tabindex="-1">20.4.6 读取拖放文件 <a class="header-anchor" href="#_20-4-6-读取拖放文件" aria-hidden="true">#</a></h4><p>把文件拖到可接受拖放的元素上，会触发<code>drop</code>事件，被放置的文件可以通过事件的<code>event.dataTransfer.files</code>属性读取，这个属性保存着一组<code>File</code>对象，就像<code>&lt;input type=&quot;file&quot;/&gt;</code>元素一样。</p><h3 id="_20-10-计时-api" tabindex="-1">20.10 计时 API <a class="header-anchor" href="#_20-10-计时-api" aria-hidden="true">#</a></h3><h4 id="_20-10-1-highresolution-time-api" tabindex="-1">20.10.1 HighResolution Time API <a class="header-anchor" href="#_20-10-1-highresolution-time-api" aria-hidden="true">#</a></h4><p><code>window.performance.now()</code>返回一个微秒精度的浮点值，这个计时器在执行上下文创建时从 0 开始计时。相当于从打开页面开始经过的毫秒数。</p><p><code>performance.timeOrigin</code>属性返回计时器初始化时全局系统时钟的值，即<code>window.performance.now()</code>的 0 时的<code>Date.now()</code>值。</p><h4 id="_20-10-2-performance-timeline-api" tabindex="-1">20.10.2 Performance Timeline API <a class="header-anchor" href="#_20-10-2-performance-timeline-api" aria-hidden="true">#</a></h4><ul><li><p>1.User Timing APi</p><p>用于记录和分析自定义性能条目，如下：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">mark</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">start</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;">(</span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> i </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;">i</span><span style="color:#89DDFF;">&lt;</span><span style="color:#F78C6C;">1e5</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;">i</span><span style="color:#89DDFF;">++&gt;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">{}</span></span>
<span class="line"><span style="color:#A6ACCD;">performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">mark</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">end</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">measure</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">runtime</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">start</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">end</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">/*</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">detail: null</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">duration: 7953.07499999553</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">entryType: &quot;measure&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">name: &quot;runtime&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">startTime: 63369246.675000004</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">*/</span></span>
<span class="line"></span></code></pre></div><p>以上，duration 即 for 循环运行的时间（毫秒精度），就不需要用以前的<code>Date.now()</code>来计算差值看运行时间了。</p></li><li><p>2.Navigation Timing API</p><p>此 api 提供了高精度时间戳，用于度量当前页面的加载速度。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getEntriesByType</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">navigation</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">/*</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">connectEnd: 1.9449999963399023</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">connectStart: 1.9449999963399023</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">decodedBodySize: 200587</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domComplete: 2418.6749999935273</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domContentLoadedEventEnd: 1949.2800000007264</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domContentLoadedEventStart: 1008.2999999867752</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domInteractive: 1008.2399999955669</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domainLookupEnd: 1.9449999963399023</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domainLookupStart: 1.9449999963399023</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">duration: 2421.3999999919906</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">encodedBodySize: 75816</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">entryType: &quot;navigation&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">fetchStart: 1.9449999963399023</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">initiatorType: &quot;navigation&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">loadEventEnd: 2421.3999999919906</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">loadEventStart: 2418.7000000092667</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">name: &quot;https://www.ituring.com.cn/book/tupubarticle/32506#20.5&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">nextHopProtocol: &quot;http/1.1&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">redirectCount: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">redirectEnd: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">redirectStart: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">requestStart: 7.099999987985939</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">responseEnd: 285.29999998863786</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">responseStart: 234.73500000545755</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">secureConnectionStart: 1.9449999963399023</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">serverTiming: []</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">startTime: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">transferSize: 76167</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">type: &quot;reload&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">unloadEventEnd: 258.56499999645166</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">unloadEventStart: 258.39999999152496</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">workerStart: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">*/</span></span>
<span class="line"></span></code></pre></div><p>以上，duration 即页面全部加载完成的时间，差不多<code>load</code>事件发生的时候；domContentLoadedEventEnd 就是<code>DOMContentLoaded</code>事件发生时。</p></li><li><p>3.Resource Timing API</p><p>用于度量当前页面加载时请求资源的速度，描述资源加载的速度；</p><p>以下示例，name 是加载资源的 URL，duration 是加载时间（毫秒），即 requestStart 和 requestEnd 的差值。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> resourceOne </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getEntriesByType</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resource</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(resourceOne)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">/*</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">connectEnd: 377.25000000500586</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">connectStart: 377.25000000500586</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">decodedBodySize: 403406</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domainLookupEnd: 377.25000000500586</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">domainLookupStart: 377.25000000500586</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">duration: 611.7799999919953</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">encodedBodySize: 91775</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">entryType: &quot;resource&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">fetchStart: 377.25000000500586</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">initiatorType: &quot;link&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">name: &quot;https://www.ituring.com.cn/ituring/css?v=tWSB7T4opubgn-3FdYTWHF5iHQQZvv8-Zl66ak_h2Rg1&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">nextHopProtocol: &quot;http/1.1&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">redirectEnd: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">redirectStart: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">requestStart: 387.30499999655876</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">responseEnd: 989.0299999970011</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">responseStart: 880.025000005844</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">secureConnectionStart: 377.25000000500586</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">serverTiming: []</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">startTime: 377.25000000500586</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">transferSize: 92166</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">workerStart: 0</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">*/</span></span>
<span class="line"></span></code></pre></div><p>通过计算分析各个资源不同的时间差，可以更全面地审视浏览器加载页面的过程，发现性能瓶颈。</p></li></ul><h3 id="_20-11-web-组件" tabindex="-1">20.11 Web 组件 <a class="header-anchor" href="#_20-11-web-组件" aria-hidden="true">#</a></h3><h4 id="_20-11-1-html-模板" tabindex="-1">20.11.1 HTML 模板 <a class="header-anchor" href="#_20-11-1-html-模板" aria-hidden="true">#</a></h4><p>主要使用<code>&lt;template&gt;</code>元素，不会渲染到页面上</p><h4 id="_20-11-2-影子-dom" tabindex="-1">20.11.2 影子 DOM <a class="header-anchor" href="#_20-11-2-影子-dom" aria-hidden="true">#</a></h4><p>会渲染到页面上，用来实现 DOM 封装，让 css 样式和 css 选择符可以限制在影子 DOM 树而不是整个顶级 DOM 树种。主要使用<code>attachShadow()</code>方法。</p><p>如下实例，p 元素的样式互不影响。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// &lt;div id=&quot;shdow-root&quot;&gt;&lt;/div&gt;</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> shadowRoot </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">getElementById</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">shdow-root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> (</span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> c </span><span style="color:#89DDFF;">of</span><span style="color:#A6ACCD;"> [</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">green</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">red</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">blue</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">]) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">div</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">createElement</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">shadowDom</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">div</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">attachShadow</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> mode</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">open</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">shadowDom</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">innerHTML</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#C3E88D;">       &lt;p&gt;</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">c</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;">&lt;/p&gt;</span></span>
<span class="line"><span style="color:#C3E88D;">       &lt;style&gt;</span></span>
<span class="line"><span style="color:#C3E88D;">          p{</span></span>
<span class="line"><span style="color:#C3E88D;">            color:</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">c</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;">;</span></span>
<span class="line"><span style="color:#C3E88D;">          }</span></span>
<span class="line"><span style="color:#C3E88D;">        &lt;/style&gt;</span></span>
<span class="line"><span style="color:#C3E88D;">       </span><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">shadowRoot</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">appendChild</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">div</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h4 id="_20-11-3-自定义元素" tabindex="-1">20.11.3 自定义元素 <a class="header-anchor" href="#_20-11-3-自定义元素" aria-hidden="true">#</a></h4><p>简单介绍下，就是让自己编写的元素可以让浏览器识别，并有对应的生命周期。</p><p>主要使用<code>customElements.define()</code>方法</p><p>如下定义一个自定义元素：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">class</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">FooElement</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">extends</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">HTMLElement</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">constructor</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">super</span><span style="color:#F07178;">()</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">x-foo</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">customElements</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">define</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">x-foo</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> FooElement)</span></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">body</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">innerHTML </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#C3E88D;">&lt;x-foo&gt;&lt;/x-foo&gt;</span></span>
<span class="line"><span style="color:#C3E88D;">&lt;x-foo&gt;&lt;/x-foo&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// x-foo</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// x-foo</span></span>
<span class="line"></span></code></pre></div><p>自定义元素名称必须至少包含一个不在名称开头和末尾的连字符，而且元素标签不能自关闭。</p><h3 id="_20-12-web-cryptography-api" tabindex="-1">20.12 Web Cryptography API <a class="header-anchor" href="#_20-12-web-cryptography-api" aria-hidden="true">#</a></h3><p>Web Cryptography API 让生成随机数、加密和签名消息成为了一类特性。规范了 JavaScript 如何以安全和符合惯例的方式实现加密。</p><h4 id="_20-12-2-使用-subtlecrypto-对象" tabindex="-1">20.12.2 使用 SubtleCrypto 对象 <a class="header-anchor" href="#_20-12-2-使用-subtlecrypto-对象" aria-hidden="true">#</a></h4><p>Web Cryptography API 重头特性都暴露在了<code>SubtleCrypto</code>对象上，可通过<code>window.crypto.subtle</code>访问，该对象只能在安全上下文<code>https</code>中使用，非安全环境中是<code>undefined</code>.</p><h2 id="_21-错误处理与调试" tabindex="-1">21 错误处理与调试 <a class="header-anchor" href="#_21-错误处理与调试" aria-hidden="true">#</a></h2><p><code>try catch</code>语句块的 catch 的参数必须为它定义名称</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">try</span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">}</span><span style="color:#89DDFF;font-style:italic;">catch</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 不正确的</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">try</span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">}</span><span style="color:#89DDFF;font-style:italic;">catch</span><span style="color:#A6ACCD;">(e)</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 正确</span></span>
<span class="line"></span></code></pre></div><p><code>try catch finally</code>语句块的<code>finally</code>子句一旦定义将始终运行，即使<code>try/catch</code>中使用了<code>return</code>。如下，testTry 始终返回 0.</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">testTry</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">try</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">catch</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">e</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">2</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">finally</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">0</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h2 id="_23-json" tabindex="-1">23 JSON <a class="header-anchor" href="#_23-json" aria-hidden="true">#</a></h2><h3 id="_23-1-语法" tabindex="-1">23.1 语法 <a class="header-anchor" href="#_23-1-语法" aria-hidden="true">#</a></h3><p>json 语法支持 3 中类型的值，简单值、对象、数组。</p><p>其中简单值字符串、数值、布尔值和<code>null</code>可以在 json 中出现，<code>undefined</code>不可以，会被忽略.</p><p>字符串必须使用双引号。</p><h2 id="_24-网络请求与远程资源" tabindex="-1">24 网络请求与远程资源 <a class="header-anchor" href="#_24-网络请求与远程资源" aria-hidden="true">#</a></h2><h3 id="_24-4-替代性跨源技术" tabindex="-1">24.4 替代性跨源技术 <a class="header-anchor" href="#_24-4-替代性跨源技术" aria-hidden="true">#</a></h3><h4 id="_24-4-1-图片探测" tabindex="-1">24.4.1 图片探测 <a class="header-anchor" href="#_24-4-1-图片探测" aria-hidden="true">#</a></h4><p>利用<code>&lt;img&gt;</code>标签实现跨域，一般用来埋点、跟踪、广告记录等，不需要读取响应内容的场景</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> img </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Image</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">img</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onload</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">done</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">img</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">src </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">https://www.nuobel.com/test?name=huyu</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"></span></code></pre></div><h4 id="_24-4-2-jsonp" tabindex="-1">24.4.2 JSONP <a class="header-anchor" href="#_24-4-2-jsonp" aria-hidden="true">#</a></h4><p>JSONP 是&quot;JSON with padding&quot;的简写，原理是使用<code>&lt;script&gt;</code>的<code>src</code>属性指定跨域 URL 来实现，可访问响应内容，只是不好确定是否失败，如下：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 前端</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handleResponse</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">response</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">response</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> script </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">createElement</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">script</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">script</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">src </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">http://freegeoip.net/json/?callback=handleResponse</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">body</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">insertBefore</span><span style="color:#A6ACCD;">(script</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">body</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">firstChild)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 服务端返回的内容</span></span>
<span class="line"><span style="color:#82AAFF;">handleResponse</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hello</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><h3 id="_24-5-fetch-api" tabindex="-1">24.5 Fetch API <a class="header-anchor" href="#_24-5-fetch-api" aria-hidden="true">#</a></h3><h2 id="_25-客户端存储" tabindex="-1">25 客户端存储 <a class="header-anchor" href="#_25-客户端存储" aria-hidden="true">#</a></h2><h3 id="_25-1-cookie" tabindex="-1">25.1 cookie <a class="header-anchor" href="#_25-1-cookie" aria-hidden="true">#</a></h3><p>响应 HTTP 请求设置 cookie：</p><div class="language-http"><button title="Copy Code" class="copy"></button><span class="lang">http</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#A6ACCD;">HTTP/1.1 200 OK</span></span>
<span class="line"><span style="color:#F07178;">Content-type</span><span style="color:#F78C6C;">:</span><span style="color:#C3E88D;">text/html</span></span>
<span class="line"><span style="color:#F07178;">Set-Cookie</span><span style="color:#F78C6C;">:</span><span style="color:#C3E88D;">name=value</span></span>
<span class="line"></span></code></pre></div><p>之后的每个请求 HTTP 头部都会加入 cookie:</p><div class="language-http"><button title="Copy Code" class="copy"></button><span class="lang">http</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">GET</span><span style="color:#A6ACCD;"> /index.js </span><span style="color:#F78C6C;">HTTP</span><span style="color:#A6ACCD;">/</span><span style="color:#F78C6C;">1.1</span></span>
<span class="line"><span style="color:#F07178;">Cookie</span><span style="color:#F78C6C;">:</span><span style="color:#C3E88D;">name=value</span></span>
<span class="line"></span></code></pre></div><h3 id="_25-2-web-storage" tabindex="-1">25.2 Web Storage <a class="header-anchor" href="#_25-2-web-storage" aria-hidden="true">#</a></h3><h4 id="_25-2-2-sessionstorage-对象" tabindex="-1">25.2.2 sessionStorage 对象 <a class="header-anchor" href="#_25-2-2-sessionstorage-对象" aria-hidden="true">#</a></h4><p>所有现代浏览器在实现存储写入时都使用了<strong>同步阻塞</strong>方式，写入的任何数据都可以立即被读取。</p><h4 id="_25-2-3-localstorage" tabindex="-1">25.2.3 localStorage <a class="header-anchor" href="#_25-2-3-localstorage" aria-hidden="true">#</a></h4><p><code>localStorage</code>会保留到通过 JavaScript 删除或用户清楚浏览器缓存。</p><h2 id="_26-模块" tabindex="-1">26 模块 <a class="header-anchor" href="#_26-模块" aria-hidden="true">#</a></h2><h3 id="_26-3-使用-es6-之前的模块加载器" tabindex="-1">26.3 使用 ES6 之前的模块加载器 <a class="header-anchor" href="#_26-3-使用-es6-之前的模块加载器" aria-hidden="true">#</a></h3><h4 id="_26-3-1-commonjs" tabindex="-1">26.3.1 CommonJS <a class="header-anchor" href="#_26-3-1-commonjs" aria-hidden="true">#</a></h4><p>CommonJS 规范概述了同步声明依赖的模块定义。这个规范<strong>主要用于服务器端</strong>实现模块化代码组织，常用于 NodeJs 中。</p><p>CommonJS 模块定义使用<code>require()</code>指定依赖，而使用<code>exports()</code>对象定义自己的公共 API。如下：</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#C792EA;">var</span><span style="color:#A6ACCD;"> moduleB </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">./moduleB</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#89DDFF;">module.exports</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">stuff</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> moduleB</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">doStuff</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>无论一个模块在<code>require()</code>中被引用多少次，模块永远是单例。即只会被加载一次，第一次加载后会被缓存，后续加载会取得缓存的模块。</p><h4 id="_26-3-2-amd-异步模块定义" tabindex="-1">26.3.2 AMD（异步模块定义） <a class="header-anchor" href="#_26-3-2-amd-异步模块定义" aria-hidden="true">#</a></h4><p>AMD(Asynchronous Module Definition)的模块定义系统以浏览器为目标执行环境。</p><p>AMD 模块实现的核心是用函数包装模块定义，关键字是全局的<code>define</code>，它由 AMD 加载器库来实现。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#676E95;font-style:italic;">// ID为moduleA的模块定义，它依赖moduleB</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// moduleB会异步加载</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 所有依赖项加载完后会执行回调函数，并把依赖项作为参数</span></span>
<span class="line"><span style="color:#82AAFF;">define</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">moduleA</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> [</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">moduleB</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">moduleB</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> stuff</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">moduleB</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">doStuff</span><span style="color:#F07178;">() </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><h4 id="_26-3-3-通用模块定义" tabindex="-1">26.3.3 通用模块定义 <a class="header-anchor" href="#_26-3-3-通用模块定义" aria-hidden="true">#</a></h4><p>UMD（Universal Module Definition）规范是为了统一 CommonJS 和 AMD 生态系统而生的。用于创建这两个系统都可以使用的模块代码。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight" tabindex="0"><code><span class="line"><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;">(</span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">root</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">factory</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">typeof</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">define</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">===</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">function</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">define</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">amd</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// AMD。注册为匿名模块</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">define</span><span style="color:#F07178;">([</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">moduleB</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">factory</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">typeof</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">module</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">===</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">object</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;&amp;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">module.exports</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// Node。不支持严格CommonJS</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 但可以在Node这样支持module.exports的</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 类CommonJS环境下使用</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">module.exports</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">factory</span><span style="color:#F07178;">(</span><span style="color:#82AAFF;">require</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;"> moduleB </span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">))</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 浏览器全局上下文（root是window）</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">root</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">returnExports</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">factory</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">root</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">moduleB</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)(</span><span style="color:#89DDFF;">this,</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">moduleB</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 以某种方式使用moduleB</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 将返回值作为模块的导出</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 这个例子返回了一个对象</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 但是模块也可以返回函数作为导出值</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><h4 id="_26-3-4-模块加载器终将没落" tabindex="-1">26.3.4 模块加载器终将没落 <a class="header-anchor" href="#_26-3-4-模块加载器终将没落" aria-hidden="true">#</a></h4><p>随着 ES6 引入了模块规范，原生浏览器的逐渐支持意味着加载器及其他预处理器不再必要。</p><h3 id="_26-4-模块标签及定义" tabindex="-1">26.4 模块标签及定义 <a class="header-anchor" href="#_26-4-模块标签及定义" aria-hidden="true">#</a></h3><h4 id="_26-4-3-模块行为" tabindex="-1">26.4.3 模块行为 <a class="header-anchor" href="#_26-4-3-模块行为" aria-hidden="true">#</a></h4><p>ES6 模块借用了 CommonJS 和 AMD 的很多优秀特性。</p><ul><li>模块代码只在加载后执行</li><li>模块只能加载一次</li><li>模块是单例（只执行一次）</li><li>模块可以定义公共接口</li><li>模块可以请求加载其它模块</li><li>支持循环依赖</li></ul><p>同时，ES6 模块系统也增加了一些新行为：</p><ul><li>默认在严格模式下执行</li><li>不共享全局命名空间</li><li>模块顶级<code>this</code>的值是<code>undefined</code></li><li>模块中的<code>var</code>声明不会添加到<code>window</code>对象</li><li>模块是异步加载和执行的</li></ul><h4 id="_26-4-4-模块导出" tabindex="-1">26.4.4 模块导出 <a class="header-anchor" href="#_26-4-4-模块导出" aria-hidden="true">#</a></h4><p><code>export</code>关键字必须在模块顶级，不能嵌套在某个块中</p><h4 id="_26-4-5-模块导入" tabindex="-1">26.4.5 模块导入 <a class="header-anchor" href="#_26-4-5-模块导入" aria-hidden="true">#</a></h4><p>同样，<code>import</code>关键字必须出现在模块的顶级</p></div></div></main><!--[--><!--]--><footer class="VPDocFooter" data-v-c5936a1e data-v-e033cd21><div class="edit-info" data-v-e033cd21><!----><div class="last-updated" data-v-e033cd21><p class="VPLastUpdated" data-v-e033cd21 data-v-355aa5ef>更新时间: <time datetime="2023-03-01T15:45:52.000Z" data-v-355aa5ef></time></p></div></div><div class="prev-next" data-v-e033cd21><div class="pager" data-v-e033cd21><a class="pager-link prev" href="/blog/readingNotes/jsgc4.html" data-v-e033cd21><span class="desc" data-v-e033cd21>前一篇</span><span class="title" data-v-e033cd21>第1-13章</span></a></div><div class="has-prev pager" data-v-e033cd21><!----></div></div></footer><!--[--><!--]--></div></div></div></div></div><!----><!--[--><!--]--></div></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"about_me.md\":\"a6963ed5\",\"about_contact.md\":\"753dd087\",\"blog_interviews_project-for-frontend-interview-questions-collection.md\":\"3ac3f621\",\"blog_svg_jiaohu.md\":\"bdc89024\",\"index.md\":\"ac84e241\",\"blog_svg_lujing.md\":\"2247252e\",\"blog_svg_lvjing.md\":\"7fb98f9e\",\"blog_svg_rumen.md\":\"760fcfc8\",\"blog_svg_tuanhejianbian.md\":\"1d67f731\",\"blog_svg_userspaceonuse-and-objectboundingbox.md\":\"7135675e\",\"blog_svg_wendangjiegou.md\":\"659e2114\",\"english_how.md\":\"47ca54fc\",\"blog_svg_zuobiaoxitong.md\":\"9f073aa7\",\"blog_svg_zuobiaoxitongbianhuan.md\":\"09c91562\",\"english_howtolearnword.md\":\"29e67a9c\",\"english_plan.md\":\"d3863f0d\",\"english_string.md\":\"afd02e54\",\"blog_interviews_css-for-frontend-interview-questions-collection.md\":\"ad8ec08c\",\"blog_interviews_index.md\":\"7922302b\",\"blog_interviews_javascript-for-frontend-interview-questions-collection.md\":\"1f97ba08\",\"blog_interviews_mian-shi-xin-de.md\":\"f249f58c\",\"blog_interviews_pingtouge-interview-questions-collection.md\":\"01898e13\",\"life_car_baoxian.md\":\"1a0484fd\",\"life_index.md\":\"294ee10b\",\"life_car_jiaotongshiguchuli.md\":\"2dfb478a\",\"life_car_kaiche.md\":\"fb68bff5\",\"photograph_fujifilm_renxiangpeifang.md\":\"df9d71f0\",\"photograph_fujifilm_jiappianjichu.md\":\"e4797107\",\"blog_readingnotes_browserprinciple.md\":\"5600b029\",\"blog_interviews_webpack-for-frontend-interview-questions-collection.md\":\"5e087073\",\"photograph_fujifilm_fengguangpeifang.md\":\"1f3c5cc8\",\"blog_summary_20210702.md\":\"992c6ebc\",\"blog_summary_20210716.md\":\"27df70fd\",\"blog_summary_20210723.md\":\"b3df6f63\",\"blog_summary_20210730.md\":\"0fd6c31f\",\"blog_readingnotes_jsgc4-2.md\":\"754107dd\",\"blog_summary_20210806.md\":\"8ede013a\",\"blog_svg_caijianhemengban.md\":\"345a71fa\",\"blog_readingnotes_jsgc4.md\":\"badec6ec\",\"blog_2020_07_accumulation-fund-transform.md\":\"ea36b833\",\"blog_svg_jibenxingzhuang.md\":\"3d07ebc2\",\"photograph_home.md\":\"289914d9\",\"photograph_fujifilm_xiangjishezhi.md\":\"c859f451\",\"photograph_sheyingzhishi.md\":\"7db1fab8\",\"photograph_xiangjixuanze.md\":\"b38cb6f4\",\"wemedia_what.md\":\"1d28f58c\",\"wemedia_emoji.md\":\"234e5631\",\"blog_2020_07_css-modules-docs.md\":\"4575442d\",\"blog_2020_07_git-docs.md\":\"22c9808c\",\"blog_2020_07_http-cache-and-nginx-config.md\":\"82b01b17\",\"blog_svg_donghua.md\":\"87326708\",\"blog_2020_06_gatsby-markdown-blog-system.md\":\"87de2558\",\"blog_2020_06_ubuntu14.04-install-nginx-for-source-code.md\":\"eff6df3c\",\"blog_2020_07_throttle-and-debounce.md\":\"745f9ff3\",\"blog_2020_07_regex-in-javascript.md\":\"375103f6\",\"blog_finance_income.md\":\"90b9a5cf\",\"blog_interviews_safe-for-frontend-interview-questions-collection.md\":\"6ae808c2\",\"blog_2020_07_vim-docs.md\":\"50a62a76\",\"blog_2020_08_fiddler.md\":\"29bf9a9b\",\"blog_2020_11_webpack-how-to-load-chunks.md\":\"2fc96bb0\",\"blog_2020_07_use-react-framework-web-site.md\":\"f836a6bd\",\"blog_interviews_algorithm-javascript.md\":\"72bdd42b\",\"blog_summary_20210611.md\":\"4cc8a1ab\",\"blog_summary_20210529.md\":\"fb886442\",\"blog_interviews_babel-for-frontend-interview-questions-collection.md\":\"495cb8da\",\"blog_summary_20210124.md\":\"ee3946e0\",\"blog_summary_20210619.md\":\"ef11c68e\",\"blog_summary_20210626.md\":\"5d8d583c\",\"blog_svg_wenben.md\":\"4aaeb73b\",\"blog_interviews_html-for-frontend-interview-questions-collection.md\":\"78197e40\",\"blog_interviews_react-for-frontend-interview-questions-collection.md\":\"90e3af48\",\"blog_interviews_http-for-frontend-interview-questions-collection.md\":\"1129730d\",\"blog_frontend_library.md\":\"34c972ff\",\"blog_readingnotes_reactandnodejs.md\":\"8a99114b\"}")</script>
    <script type="module" async src="/assets/app.6facf8ba.js"></script>
    
  </body>
</html>